home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / ctask.zip / TSKDOS.ASM < prev    next >
Assembly Source File  |  1988-07-01  |  21KB  |  1,039 lines

  1. ;
  2. ;    CTask - DOS access module.
  3. ;
  4. ;    Public Domain Software written by
  5. ;        Thomas Wagner
  6. ;        Patschkauer Weg 31
  7. ;        D-1000 Berlin 33
  8. ;        West Germany
  9. ;
  10. ;
  11. ; The DOS interrupt (and the related direct disk I/O interrupts) are
  12. ; not reentrant. Access to DOS thus has to be channelled such that no
  13. ; two tasks use DOS services simultaneously. However, there is one
  14. ; exception to this rule. Whenever DOS is waiting for the keyboard, it
  15. ; issues a special interrupt, INT 28h, to signal that background
  16. ; processing for functions > 0Ch may be performed. This is used in the
  17. ; DOS interface for CTask in the following manner:
  18. ;
  19. ;   A task issuing a DOS interrupt will request one of two resources:
  20. ;   "lower_dos" for functions <= 0C, "upper_dos" for functions > 0C.
  21. ;   If a task gets access to "lower_dos", it will also request the
  22. ;   "upper_dos" resource to lock out other tasks from interrupting.
  23. ;   This "upper_dos" resource is shortly released on each INT 28, and
  24. ;   then immediately reclaimed, with task priority temporarily raised
  25. ;   to the maximum value. The first task waiting to execute a 
  26. ;   function > 0C will thus be scheduled to execute the request, but
  27. ;   the resource will be reassigned to the INT 28 handler as soon as
  28. ;   this request terminates, so the waiting task will not be delayed too
  29. ;   long.
  30. ;
  31. ; There are two additional safety measures which have to be taken to
  32. ; avoid getting into conflicts with other resident background programs,
  33. ; especially the DOS PRINT background spooler:
  34. ;
  35. ;   Before requesting any resource, the status of the DOS critical section
  36. ;   flag is checked. If this flag is set, the task is made waiting for
  37. ;   the flag to be cleared.
  38. ;   Only the task that set the flag will be allowed access to DOS.
  39. ;
  40. ;   Before actually executing the request, the status of the DOS in-use
  41. ;   flag is checked. If this flag is set, the task enters a busy waiting
  42. ;   loop, calling the scheduler so that the processor is not tied up.
  43. ;
  44. ; NOTE: The method for checking the status of DOS is described in-depth
  45. ;    in the book "The MS-DOS Encyclopedia" from Microsoft Press, in
  46. ;    the chapter on TSR programming. The logic in this module was
  47. ;    developed without the help of this book, so if you compare
  48. ;    the code here with the routines in the Encyclopedia, you may
  49. ;    notice that not all re-entry conditions are checked here.
  50. ;    According to my experience with debugging TSR's and CTask, the
  51. ;    logic should be sufficient for all but the most obscure TSR's.
  52. ;    If you want to be completely on the safe side, you might consider
  53. ;    adding the more thorough checks listed in the Encyclopedia.
  54. ;
  55. ;
  56.     name    tskdos
  57. ;
  58.     .model    large
  59. ;
  60.     public    _tsk_install_dos
  61.     public    _tsk_remove_dos
  62. ;
  63. ;
  64.     include    tsk.mac
  65. ;
  66. CSECT        =    2ah    ; Critical Section Interrupt
  67. get_in_use_flag    =    34h    ; DOS-function to get in_use_flag address
  68. ;
  69. ;
  70. intseg    segment at 0
  71.         org    20h*4
  72. termoff        dw    ?    ; program terminate vector
  73. termseg        dw    ?
  74.         org    21h*4
  75. idosoff        dw    ?    ; dos interrupt
  76. idosseg        dw    ?
  77.         org    25h*4
  78. absreadoff    dw    ?    ; absolute disk read
  79. absreadseg    dw    ?
  80.         org    26h*4
  81. abswriteoff    dw    ?    ; absolute disk write
  82. abswriteseg    dw    ?
  83.         org    27h*4
  84. keepoff        dw    ?    ; Terminate but stay resident
  85. keepseg        dw    ?
  86.         org    28h*4
  87. idleoff        dw    ?    ; dos idle interrupt
  88. idleseg        dw    ?
  89.         org    CSECT*4
  90. csectoff    dw    ?    ; dos critical section
  91. csectseg    dw    ?
  92. ;
  93. intseg    ends
  94. ;
  95. ;----------------------------------------------------------------------------
  96. ;
  97. ;    Variables
  98. ;
  99.     .data
  100. ;
  101.     extrn    _tsk_current: dword
  102. ;
  103. term_err_msg    db    0dh,0ah,"Program terminated - CTask uninstalled"
  104.         db    0dh,0ah,'$'
  105. ;
  106. idle_active    db    0            ; Idle-Interrupt active
  107. dos310        db    0        ; DOS version >= 3.10
  108. ;
  109.     IF    TSK_NAMEPAR
  110. ldos_name    db    "DOSUPPER",0
  111. udos_name    db    "DOSLOWER",0
  112. cdos_name    db    "DOSCRIT",0
  113.     ENDIF
  114. ;
  115.     .data?
  116. ;
  117. in_use        dd    ?        ; Adress of DOS in-use-flag
  118. in_error    dd    ?        ; Adress of DOS error-mode-flag
  119. ;
  120. lower_dos    resource <>
  121. upper_dos    resource <>
  122. critical    flag <>
  123. ;
  124. idle_ss        dw    ?        ; Stack save
  125. idle_sp        dw    ?
  126. ;
  127.         dw    256 dup(?)    ; Stack for IDLE-Interrupt
  128. local_stack    label    word
  129. ;
  130.     .code
  131. ;
  132. ;    Original Interrupt-Entries
  133. ;
  134. savtermoff    dw    ?        ; Terminate vector save
  135. savtermseg    dw    ?
  136. ;
  137. savdos        label    dword        ; original DOS-Entry
  138. savdosoff    dw    ?
  139. savdosseg    dw    ?
  140. ;
  141. savidle        label    dword        ; original IDLE-Entry
  142. savidleoff    dw    ?
  143. savidleseg    dw    ?
  144. ;
  145. savcsect    label    dword        ; Critical Section save
  146. savcsectoff    dw    ?
  147. savcsectseg    dw    ?
  148. ;
  149. savabsread    label    dword        ; Absolute Disk Read save
  150. savabsreadoff    dw    ?
  151. savabsreadseg    dw    ?
  152. ;
  153. savabswrite    label    dword        ; Absolute Disk Write save
  154. savabswriteoff    dw    ?
  155. savabswriteseg    dw    ?
  156. ;
  157. savkeepoff    dw    ?        ; Terminate resident vector save
  158. savkeepseg    dw    ?
  159. ;
  160. critsect_active    db    0        ; DOS Critical Section active
  161. ctask_active    db    0        ; CTask DOS call active
  162. crit_task    dd    ?        ; Task requesting critical section
  163. ;
  164. ;
  165. dos    macro
  166.     pushf
  167.     cli
  168.     call    cs:savdos
  169.     endm
  170. ;
  171. ;---------------------------------------------------------------------------
  172. ;
  173.     .code
  174. ;
  175.     extrn    _create_resource: far
  176.     extrn    _delete_resource: far
  177.     extrn    _request_resource: far
  178.     extrn    _release_resource: far
  179.     extrn    _create_flag: far
  180.     extrn    _delete_flag: far
  181.     extrn    _set_flag: far
  182.     extrn    _clear_flag: far
  183.     extrn    _wait_flag_clear: far
  184.     extrn    _remove_tasker: far
  185.     extrn    scheduler: far
  186. ;
  187. ;
  188. ;    void tsk_install_dos (void)
  189. ;
  190. ;        Install DOS handler
  191. ;
  192. _tsk_install_dos    proc
  193. ;
  194. ;    create needed resources & flags
  195. ;
  196.     IF    TSK_NAMEPAR
  197.     mov    ax,offset udos_name
  198.     push    ds
  199.     push    ax
  200.     ENDIF
  201.     mov    ax,offset upper_dos
  202.     push    ds
  203.     push    ax
  204.     call    _create_resource
  205.     IF    TSK_NAMEPAR
  206.     add    sp,8
  207.     ELSE
  208.     add    sp,4
  209.     ENDIF
  210. ;
  211.     IF    TSK_NAMEPAR
  212.     mov    ax,offset ldos_name
  213.     push    ds
  214.     push    ax
  215.     ENDIF
  216.     mov    ax,offset lower_dos
  217.     push    ds
  218.     push    ax
  219.     call    _create_resource
  220.     IF    TSK_NAMEPAR
  221.     add    sp,8
  222.     ELSE
  223.     add    sp,4
  224.     ENDIF
  225. ;
  226.     IF    TSK_NAMEPAR
  227.     mov    ax,offset cdos_name
  228.     push    ds
  229.     push    ax
  230.     ENDIF
  231.     mov    ax,offset critical
  232.     push    ds
  233.     push    ax
  234.     call    _create_flag
  235.     IF    TSK_NAMEPAR
  236.     add    sp,8
  237.     ELSE
  238.     add    sp,4
  239.     ENDIF
  240. ;
  241. ;    Get the address of DOS's in_use-flag. This flag indicates that
  242. ;    DOS is already active. This might happen if there are other
  243. ;    background tasks, like popups or print spoolers, active in
  244. ;    parallel to CTask.
  245. ;    This is also the address of the critical error flag in DOS. Beginning 
  246. ;    with DOS 3.10 the flag is located one byte before the in_use_flag.
  247. ;    With older DOS versions, we would have to search through DOS for the 
  248. ;    address. This is omitted here, but you could include the code
  249. ;    for pre 3.1 versions from pages 378-379 of the MS-DOS Encyclopedia.
  250. ;    
  251.     mov    ah,get_in_use_flag
  252.     int    21h
  253.     mov    word ptr in_use,bx
  254.     mov    word ptr in_use+2,es
  255.     mov    word ptr in_error+2,es
  256. ;
  257.     mov    ah,30h
  258.     int    21h
  259.     cmp    ah,3
  260.     jb    not_dos3
  261.     cmp    ah,0ah
  262.     je    not_dos3    ; OS/2 compatibility box
  263.     cmp    al,10
  264.     jb    not_dos3
  265.     inc    dos310
  266.     dec    bx
  267.     mov    word ptr in_error,bx
  268.     jmp    short save_ints
  269. ;
  270. not_dos3:
  271.  
  272. ;
  273. ;    Save old interrupt vectors
  274. ;
  275. save_ints:
  276.         push    es
  277.     xor    ax,ax
  278.     mov    es,ax
  279. ;
  280.         assume  es:intseg
  281. ;
  282.     mov    ax,termoff        ; DOS
  283.     mov    savtermoff,ax
  284.     mov    ax,termseg
  285.     mov    savtermseg,ax
  286. ;
  287.     mov    ax,idosoff        ; DOS
  288.     mov    savdosoff,ax
  289.     mov    ax,idosseg
  290.     mov    savdosseg,ax
  291. ;
  292.     mov    ax,idleoff        ; IDLE
  293.     mov    savidleoff,ax
  294.     mov    ax,idleseg
  295.     mov    savidleseg,ax
  296. ;
  297.     mov    ax,csectoff        ; Critical Section
  298.     mov    savcsectoff,ax
  299.     mov    ax,csectseg
  300.     mov    savcsectseg,ax
  301. ;
  302.     mov    ax,absreadoff        ; Absolute Disk read
  303.     mov    savabsreadoff,ax
  304.     mov    ax,absreadseg
  305.     mov    savabsreadseg,ax
  306. ;
  307.     mov    ax,abswriteoff        ; Absolute Disk write
  308.     mov    savabswriteoff,ax
  309.     mov    ax,abswriteseg
  310.     mov    savabswriteseg,ax
  311. ;
  312.     mov    ax,keepoff        ; Terminate Resident
  313.     mov    savkeepoff,ax
  314.     mov    ax,keepseg
  315.     mov    savkeepseg,ax
  316. ;
  317. ;    Enter new Interrupt-Entries
  318. ;
  319.     cli
  320.     mov    idosoff,offset dosentry        ; DOS-Entry
  321.     mov    idosseg,cs
  322.     mov    idleoff,offset idleentry    ; Idle-Entry
  323.     mov    idleseg,cs
  324.     mov    termoff,offset terminate_int    ; Terminate Process Entry
  325.     mov    termseg,cs
  326.     mov    csectoff,offset critsectint    ; Critical Section Entry
  327.     mov    csectseg,cs
  328.     mov    keepoff,offset keep_int        ; Keep Process Entry
  329.     mov    keepseg,cs
  330.     mov    absreadoff,offset absread_int    ; Absolute Disk Read Entry
  331.     mov    absreadseg,cs
  332.     mov    abswriteoff,offset abswrite_int    ; Absolute Disk Write Entry
  333.     mov    abswriteseg,cs
  334.     sti
  335.         pop     es
  336. ;
  337.     ret
  338. ;
  339.     assume    es:nothing
  340. ;
  341. _tsk_install_dos    endp
  342. ;
  343. ;
  344. ;    void tsk_remove_dos (void)
  345. ;
  346. ;        Un-install DOS handler
  347. ;
  348. _tsk_remove_dos    proc
  349. ;
  350. ;    Delete resources & flags
  351. ;
  352.     mov    ax,offset upper_dos
  353.     push    ds
  354.     push    ax
  355.     call    _delete_resource
  356.     add    sp,4
  357. ;
  358.     mov    ax,offset lower_dos
  359.     push    ds
  360.     push    ax
  361.     call    _delete_resource
  362.     add    sp,4
  363. ;
  364.     mov    ax,offset critical
  365.     push    ds
  366.     push    ax
  367.     call    _delete_flag
  368.     add    sp,4
  369. ;
  370.         push    es
  371.     xor    ax,ax
  372.     mov    es,ax
  373. ;
  374.         assume  es:intseg
  375. ;
  376. ;    Restore interrupt entries
  377. ;
  378.     cli
  379.     mov    ax,savtermoff
  380.     mov    termoff,ax
  381.     mov    ax,savtermseg
  382.     mov    termseg,ax
  383. ;
  384.     mov    ax,savdosoff
  385.     mov    idosoff,ax
  386.     mov    ax,savdosseg
  387.     mov    idosseg,ax
  388. ;
  389.     mov    ax,savidleoff
  390.     mov    idleoff,ax
  391.     mov    ax,savidleseg
  392.     mov    idleseg,ax
  393. ;
  394.     mov    ax,savcsectoff
  395.     mov    csectoff,ax
  396.     mov    ax,savcsectseg
  397.     mov    csectseg,ax
  398. ;
  399.     mov    ax,savabsreadoff
  400.     mov    absreadoff,ax
  401.     mov    ax,savabsreadseg
  402.     mov    absreadseg,ax
  403. ;
  404.     mov    ax,savabswriteoff
  405.     mov    abswriteoff,ax
  406.     mov    ax,savabswriteseg
  407.     mov    abswriteseg,ax
  408. ;
  409.     mov    ax,savkeepoff
  410.     mov    keepoff,ax
  411.     mov    ax,savkeepseg
  412.     mov    keepseg,ax
  413. ;
  414.     sti
  415. ;
  416.         pop     es
  417.     ret
  418. ;
  419.     assume    es:nothing
  420. ;
  421. _tsk_remove_dos    endp
  422. ;
  423. ;
  424. ;---------------------------------------------------------------------------
  425. ;
  426. ;    Stack-Offsets relative to BP
  427. ;
  428. caller_cs    =    4        ; Caller's CS
  429. caller_flags    =    6        ; Caller's Flags
  430. ;
  431. ;
  432. ;---------------------------------------------------------------------------
  433. ;
  434. ;    INT 25: Absolute Disk Read 
  435. ;
  436. ;    This interrupt is translated into INT 21, function C0.
  437. ;    This function is re-translated later after the necessary resources
  438. ;    have been requested.
  439. ;
  440. absread_int:
  441.     mov    ah,0c0h
  442.     jmp    short absrw_int
  443. ;
  444. ;
  445. ;---------------------------------------------------------------------------
  446. ;
  447. ;    INT 26: Absolute Disk Write
  448. ;
  449. ;    This interrupt is translated into INT 21, function C1.
  450. ;    This function is re-translated later after the necessary resources
  451. ;    have been requested.
  452. ;
  453. abswrite_int:
  454.     mov    ah,0c1h
  455. ;
  456. ;    Interrupts 25 und 26 leave the flag-word on the stack.
  457. ;    Since flags are removed in normal processing, the flag-word
  458. ;    has to be duplicated on the stack here.
  459. ;
  460. absrw_int:
  461.     push    bp            ; reserve space
  462.     push    bp            ; save BP
  463.     mov    bp,sp
  464.     sti
  465.     push    ax
  466.     mov    ax,4[bp]        ; Move return offset, segment down
  467.     mov    2[bp],ax
  468.     mov    ax,6[bp]
  469.     mov    4[bp],ax
  470.     mov    ax,8[bp]        ; duplicate flags
  471.     mov    6[bp],ax
  472.     pop    ax
  473.     push    caller_flags[bp]
  474.     jmp    short dosentry_2
  475. ;
  476. ;---------------------------------------------------------------------------
  477. ;
  478. ;    INT 27: Terminate But Stay Resident Interrupt
  479. ;
  480. ;    This interrupt is translated to INT 21, function 31.
  481. ;
  482. keep_int:
  483.     push    bp
  484.     mov    bp,sp
  485.     push    caller_flags[bp]    ; flags (bp-2)
  486.     sti                ; allow interrupts
  487. ;
  488.     add    dx,0fh            ; last addr + 0f to round
  489.     sub    dx,caller_cs[bp]    ; minus CS (= PSP)
  490.     mov    cl,4
  491.     shr    dx,cl            ; div 16 = paragraphs
  492.  
  493.     mov    ax,3100h        ; Keep process
  494.     jmp    short dosentry_2
  495. ;
  496. ;---------------------------------------------------------------------------
  497. ;
  498. ;    INT 20: Terminate Program interrupt
  499. ;
  500. ;    This interrupt is translated to INT 21, function 0.
  501. ;
  502. terminate_int:
  503.     mov    ah,0
  504. ;
  505. ;    fall through
  506. ;
  507. ;---------------------------------------------------------------------------
  508. ;
  509. ;    INT 21: DOS-Interrupt
  510. ;
  511. dosentry        proc    far
  512. ;
  513. ;    Save registers
  514. ;
  515.     push    bp
  516.     mov    bp,sp
  517.     push    caller_flags[bp]    ; flags (bp-2)
  518. ;
  519. dosentry_2:
  520.     push    es
  521.     push    ds
  522.     push    dx
  523.     push    cx
  524.     push    bx
  525.     push    ax
  526.     push    si
  527.     push    di
  528. ;
  529. ;    Here we check if the DOS critical region is active.
  530. ;    If yes, this means that some outside background process has
  531. ;    started DOS (most likely DOS PRINT).
  532. ;    To avoid busy waiting, we wait for the "critical" flag to be
  533. ;    cleared, if this is *not* the task that set the flag.
  534. ;    The task that set the critical task is *not* made waiting.
  535. ;
  536. wait_crit_loop:
  537.     cli
  538.     cmp    cs:critsect_active,0
  539.     je    no_crit
  540.     mov    ax,word ptr cs:crit_task
  541.     cmp    word ptr _tsk_current,ax
  542.     jne    wait_crit
  543.     mov    ax,word ptr cs:crit_task+2
  544.     cmp    word ptr _tsk_current+2,ax
  545.     je    no_crit
  546. ;
  547. wait_crit:
  548.     xor    ax,ax
  549.     push    ax
  550.     push    ax
  551.     mov    ax,offset critical
  552.     push    ds
  553.     push    ax
  554.     call    _wait_flag_clear
  555.     add    sp,8
  556. ;
  557. no_crit:
  558.     mov    cs:ctask_active,1    ; mark that we are active
  559.     sti                ; Interrupts allowed now
  560. ;
  561.     cld
  562.     mov    bx,SEG dgroup
  563.     mov    ds,bx
  564.     mov    es,bx
  565. ;
  566.         cmp     ah,4ch                  ; terminate?
  567.         jne     dosent_x
  568.         mov     ah,0                    ; translate to fn 0
  569. dosent_x:
  570.     cmp    ah,0ch
  571.     jbe    lower_funcs
  572.     jmp    upper_funcs
  573. ;
  574. ;    Functions 00-0C
  575. ;
  576. lower_funcs:
  577. ;
  578. ;    first, request the "lower_dos" resource
  579. ;
  580.     mov    bx,offset lower_dos
  581.     xor    cx,cx
  582.     push    cx        ; no timeout
  583.     push    cx
  584.     push    ds        ; resource address
  585.     push    bx
  586.     call    _request_resource
  587.     add    sp,8
  588. ;
  589. ;    we have it, now let's get the upper_dos resource, too
  590. ;
  591.     mov    bx,offset upper_dos
  592.     xor    cx,cx
  593.     push    cx        ; no timeout
  594.     push    cx
  595.     push    ds        ; resource address
  596.     push    bx
  597.     call    _request_resource
  598.     add    sp,8
  599. ;
  600. ;    both resources gained, now we may execute the function if dos is free
  601. ;
  602.     pop    di
  603.     pop    si
  604.     pop    ax
  605.     pop    bx
  606.     pop    cx
  607.     pop    dx
  608. ;
  609.     call    wait_dos_free
  610. ;
  611.     or    ah,ah            ; terminate ?
  612.     je    fg_terminate        ; special treatment required
  613.     cmp    ah,4ch
  614.     je    fg_terminate        ; special treatment required
  615.     pop     ds
  616.     pop    es
  617.     popf
  618.     pop    bp
  619. ;
  620.     dos                ; execute function
  621. ;
  622. ;    Now we have to release the resources.
  623. ;
  624.     pushf                ; save registers again
  625.     sti
  626.     push    es
  627.     push    ds
  628.     push    dx
  629.     push    cx
  630.     push    bx
  631.     push    ax
  632.     push    si
  633.     push    di
  634. ;
  635.     mov    bx,SEG dgroup
  636.     mov    ds,bx
  637.     mov    es,bx
  638. ;
  639.     mov    bx,offset upper_dos
  640.     push    ds        ; resource address
  641.     push    bx
  642.     call    _release_resource
  643.     add    sp,4
  644. ;
  645.     mov    bx,offset lower_dos
  646.     push    ds        ; resource address
  647.     push    bx
  648.     call    _release_resource
  649.     add    sp,4
  650. ;
  651. ;    If both resources are free now, clear the ctask_active flag to
  652. ;    allow other background processes to gain access to DOS.
  653. ;
  654.     cli
  655.     mov    ax,upper_dos.rstate
  656.         or    ax,ax
  657.         jz    no_relc
  658.     cmp    ax,lower_dos.rstate
  659.     jne    no_relc
  660.     mov    cs:ctask_active,0
  661. no_relc:
  662. ;
  663. ;    All done, restore registers and return.
  664. ;
  665.     pop    di
  666.     pop    si
  667.     pop    ax
  668.     pop    bx
  669.     pop    cx
  670.     pop    dx
  671.     pop     ds
  672.     pop    es
  673.     popf
  674. ;
  675.     ret    2            ; don't restore flags
  676. ;
  677. ;
  678. ;    The terminate request requires special treatment.
  679. ;    Since terminating the program without first un-installing
  680. ;    would crash the system, we do this here, not without telling
  681. ;    the user something went very wrong.
  682. ;
  683. fg_terminate:
  684.     cli
  685.     call    _remove_tasker
  686.     mov    dx,offset term_err_msg
  687.     mov    ah,9
  688.     int    21h
  689.     mov    ax,4cffh
  690.     int    21h
  691. ;
  692. ;--------------------------------------------------------------------------
  693. ;
  694. ;    Functions 0D and above
  695. ;
  696. upper_funcs:
  697.     mov    bx,offset upper_dos
  698.     xor    cx,cx
  699.     push    cx        ; no timeout
  700.     push    cx
  701.     push    ds        ; resource address
  702.     push    bx
  703.     call    _request_resource
  704.     add    sp,8
  705. ;
  706. ;    resource gained, now we may execute the function if dos is free
  707. ;
  708.     pop    di
  709.     pop    si
  710.     pop    ax
  711.     pop    bx
  712.     pop    cx
  713.     pop    dx
  714. ;
  715.     call    wait_dos_free
  716. ;
  717.     pop     ds
  718.     pop    es
  719. ;
  720. ;
  721. ;    Filter pseudo-functions C0/C1 (Absolute Read/Write)
  722. ;
  723.     cmp    ah,0c0h
  724.     jne    uf_exec1
  725.     popf
  726.     pop    bp
  727.     call    exec_absread
  728.     jmp    short uf_complete
  729. uf_exec1:
  730.     cmp    ah,0c1h
  731.     jne    uf_exec2
  732.     popf
  733.     pop    bp
  734.     call    exec_abswrite
  735.     jmp    short uf_complete
  736. ;
  737. uf_exec2:
  738.     popf
  739.     pop    bp
  740.     dos                ; execute function
  741. ;
  742. ;    Now we have to release the resources.
  743. ;
  744. uf_complete:
  745.     pushf                ; save registers again
  746.     sti
  747.     push    es
  748.     push    ds
  749.     push    dx
  750.     push    cx
  751.     push    bx
  752.     push    ax
  753.     push    si
  754.     push    di
  755. ;
  756.     mov    bx,SEG dgroup
  757.     mov    ds,bx
  758.     mov    es,bx
  759. ;
  760.     mov    bx,offset upper_dos
  761.     push    ds        ; resource address
  762.     push    bx
  763.     call    _release_resource
  764.     add    sp,4
  765. ;
  766. ;    If both resources are free now, clear the ctask_active flag to
  767. ;    allow other background processes to gain access to DOS.
  768. ;
  769.     cli
  770.     mov    ax,upper_dos.rstate
  771.         or    ax,ax
  772.         jz    no_relc1
  773.     cmp    ax,lower_dos.rstate
  774.     jne    no_relc1
  775.     mov    cs:ctask_active,0
  776. no_relc1:
  777. ;
  778. ;    All done, restore registers and return.
  779. ;
  780.     pop    di
  781.     pop    si
  782.     pop    ax
  783.     pop    bx
  784.     pop    cx
  785.     pop    dx
  786.     pop     ds
  787.     pop    es
  788.     popf
  789. ;
  790.     ret    2            ; don't restore flags
  791. ;
  792. ;
  793. dosentry    endp
  794. ;
  795. ;--------------------------------------------------------------------------
  796. ;
  797. ;    Absolute Read/Absolute Write.
  798. ;
  799. exec_absread    proc    near
  800.  
  801.     pushf
  802.     call    cs:savabsread
  803.     inc    sp            ; Remove flags (not using ADD,
  804.     inc    sp            ; this would clobber Carry)
  805.     ret
  806.  
  807. exec_absread    endp
  808. ;
  809. exec_abswrite    proc    near
  810.  
  811.     pushf
  812.     call    cs:savabswrite
  813.     inc    sp            ; Remove flags (not using ADD,
  814.     inc    sp            ; this would clobber Carry)
  815.     ret
  816.  
  817. exec_abswrite    endp
  818. ;
  819. ;----------------------------------------------------------------------------
  820. ;
  821. wait_dos_free    proc    near
  822. ;
  823.     push    es
  824.     push    bx
  825. in_use_loop:
  826.     cmp    idle_active,0        ; idle interrupt active?
  827.     jne    dos_free        ; then don't check for flag
  828. ;
  829.     les    bx,in_use
  830.     cmp    byte ptr es:[bx],0
  831.     jne    is_in_use
  832.     cmp    dos310,0
  833.     je    dos_free
  834.     les    bx,in_error
  835.     cmp    byte ptr es:[bx],0
  836.     je    dos_free
  837. is_in_use:
  838.     pushf
  839.     call    scheduler
  840.     jmp    in_use_loop
  841. ;
  842. dos_free:
  843.     pop    bx
  844.     pop    es
  845.     ret
  846. ;
  847. wait_dos_free    endp
  848. ;
  849. ;----------------------------------------------------------------------------
  850. ;
  851. ;    INT 28: DOS Idle Interrupt
  852. ;
  853. idleentry    proc    far
  854. ;
  855.     push    ds
  856.     push    es
  857.     push    ax
  858. ;
  859.     mov    ax,SEG dgroup
  860.     mov    ds,ax
  861.     mov    es,ax
  862. ;
  863. ;    Check if someone is waiting for upper_dos. If not, we can return
  864. ;    immediately.
  865. ;
  866.     mov    ax,word ptr upper_dos.rwaiting
  867.     or    ax,word ptr upper_dos.rwaiting+2
  868.     jz    idle_exit
  869. ;
  870. ;    Also make sure this is not a second invocation of INT 28.
  871. ;    Normally, this should never happen, but better safe than sorry.
  872. ;
  873.     cmp    idle_active,0
  874.     jne    idle_exit
  875.     inc    idle_active
  876. ;
  877. ;    someone is waiting, let's please him by releasing the resource
  878. ;
  879.     mov    idle_ss,ss        ; Switch to local stack
  880.     mov    idle_sp,sp
  881.     mov    ax,ds
  882.     mov    ss,ax
  883.     mov    sp,offset local_stack
  884. ;
  885.     sti                ; Interrupts allowed now
  886. ;
  887.         push    bx            ; save remaining regs
  888.     push    cx
  889.     push    dx
  890. ;
  891. ;    temporarily increase priority
  892. ;
  893.     les    bx,_tsk_current
  894.     push    es:prior[bx]
  895.     mov    es:prior[bx],0ffffh
  896.     push    bx
  897.     push    es
  898. ;
  899. ;    release resource & request it again
  900. ;
  901.     mov    ax,ds
  902.     mov    es,ax
  903.     mov    bx,offset upper_dos
  904.     push    ds
  905.     push    bx
  906.     call    _release_resource
  907.     add    sp,4
  908. ;
  909.     mov    bx,offset upper_dos
  910.     xor    cx,cx
  911.     push    cx
  912.     push    cx
  913.     push    ds
  914.     push    bx
  915.     call    _request_resource
  916.     add    sp,8
  917. ;
  918. ;    ready, restore priority, stack & regs
  919. ;
  920.     cli
  921.     pop    es
  922.     pop    bx
  923.     pop    es:prior[bx]
  924. ;
  925.     pop    dx
  926.     pop    cx
  927.     pop    bx
  928. ;
  929.     mov    ss,idle_ss        ; restore stack
  930.     mov    sp,idle_sp
  931. ;
  932.     mov    idle_active,0
  933. ;
  934. idle_exit:
  935.     pop    ax
  936.         pop     es
  937.     pop    ds
  938. ;
  939.     jmp    cs:savidle        ; chain to original interrupt
  940. ;
  941. idleentry    endp
  942. ;
  943. ;---------------------------------------------------------------------------
  944. ;
  945. ;    INT 2A: DOS Critical Section Interrupt.
  946. ;
  947. ;    Not documented.
  948. ;    Is used by DOS PRINT to mark Critical Regions.
  949. ;    Usage by PRINT:
  950. ;        AX = 8700 - Begin Critical Region
  951. ;                Returns:
  952. ;                Carry set if already active.
  953. ;        AX = 8701 - End Critical Region
  954. ;
  955. ;    Both these functions are handled here.
  956. ;
  957. ;    Other usage in DOS, function unknown:
  958. ;        AH = 82 (AL undefined)
  959. ;            seems to be called on DOS-Functions > 0C
  960. ;        AH = 84 (AL undefined)
  961. ;            seems to be called when DOS is idle
  962. ;
  963. ;    These functions are currently ignored.
  964. ;
  965. critsectint    proc    far
  966.  
  967.     cmp    ax,8700h    ; Enter critical region
  968.     jne    csi1
  969.     cmp    cs:critsect_active,0
  970.     stc
  971.     jnz    critsect_end
  972.     cmp    cs:ctask_active,0
  973.     stc
  974.     jnz    critsect_end
  975. ;
  976.     inc    cs:critsect_active
  977.     push    ax
  978.     push    bx
  979.     push    cx
  980.     push    dx
  981.     push    ds
  982.     push    es
  983.     mov    ax,seg dgroup
  984.     mov    ds,ax
  985.     mov    es,ax
  986.     mov    ax,word ptr _tsk_current
  987.     mov    word ptr cs:crit_task,ax
  988.     mov    ax,word ptr _tsk_current+2
  989.     mov    word ptr cs:crit_task+2,ax
  990.     mov    ax,offset critical
  991.     push    ds
  992.     push    ax
  993.     call    _set_flag
  994.     add    sp,4
  995.     pop    es
  996.     pop    ds
  997.     pop    dx
  998.     pop    cx
  999.     pop    bx
  1000.     pop    ax
  1001.     clc
  1002. critsect_end:
  1003.     ret    2
  1004. ;
  1005. csi1:
  1006.     cmp    ax,8701h    ; Leave critical region
  1007.     jne    csi2
  1008.     mov    cs:critsect_active,0
  1009.     push    ax
  1010.     push    bx
  1011.     push    cx
  1012.     push    dx
  1013.     push    ds
  1014.     push    es
  1015.     mov    ax,seg dgroup
  1016.     mov    ds,ax
  1017.     mov    es,ax
  1018.     mov    ax,offset critical
  1019.     push    ds
  1020.     push    ax
  1021.     call    _clear_flag
  1022.     add    sp,4
  1023.     pop    es
  1024.     pop    ds
  1025.     pop    dx
  1026.     pop    cx
  1027.     pop    bx
  1028.     pop    ax
  1029. csi2:
  1030.     iret
  1031. ;
  1032. critsectint    endp
  1033. ;
  1034. ;
  1035. ;---------------------------------------------------------------------------
  1036. ;
  1037.         end
  1038.  
  1039.